
#ifndef TARGET_H
#define TARGET_H

#pragma warning(disable:4251)

#include <BMap>
#include <BLine>
#include <BShape>
#include <BCamera>
#include <BLight>
#include <BPicker>
#include <BGroup>
#include <BScene>
#include <BScript>

using namespace BWE;

inline bool ComparePickHit(const BPickHit* hitA, const BPickHit* hitB)
{
	if (hitA->group() != hitB->group())
		return false;
	if (hitA->node() != hitB->node())
		return false;
	if (hitA->shape() != hitB->shape())
		return false;
	if (hitA->element() != hitB->element())
		return false;
	if (hitA->index() != hitB->index())
		return false;
	return true;
}

class Target : public BObject
{
public:
	Target(BScene* scene = 0);
	Target(BGroup* group, BScene* scene = 0);
	Target(BShape* shape, BScene* scene = 0);
	Target(BShape* shape, BNode* node, BScene* scene = 0);
	Target(BShape* shape, BGroup* group, BScene* scene = 0);
	Target(BNode* node, BScene* scene = 0);
	Target(BNode* node, BGroup* group, BScene* scene = 0);
	Target(BRestraint* restraint, BScene* scene = 0);
	Target(BRestraint* restraint, BGroup* group, BScene* scene = 0);
	Target(const Target& other);
	~Target();

	const BBox& box() const;
	const BSpace& space() const;

	void reset(BScene* scene = 0);
	void reset(BShape* shape, BScene* scene = 0);
	void reset(BGroup* group, BScene* scene = 0);
	void reset(BShape* shape, BGroup* group, BScene* scene = 0);
	void reset(BNode* node, BScene* scene = 0);
	void reset(BShape* shape, BNode* node, BScene* scene = 0);
	void reset(BNode* node, BGroup* group, BScene* scene = 0);

	void copy(const Target* other);

	BScene* scene();
	const BScene* scene() const;

	BGroup* root();
	const BGroup* root() const;

	BString path() const;

	void append(BGroup* group);
	void append(BShape* shape);
	void append(BShape* shape, BNode* nodee);
	void append(BShape* shape, BGroup* group);
	void append(BNode* node);
	void append(BNode* node, BGroup* group);
	void append(BScript* script);
	void append(BScript* script, BGroup* group);
	void append(BRestraint* restraint);
	void append(BRestraint* restraint, BGroup* group);

	bool addPickHit(BPickHit* hit);
	bool removePickHit(BPickHit* hit);
	BPickHit* matchPickHit(BPickHit* hit);

	int pickHitCount() const;
	BPickHit* pickHit(int index);
	BPickHit* pickHit(const BShape* shape);

	BNode* findNode(BNode* node) const;
	bool contain(BObject* object) const;

	BObject* object(int index) const;
	BShape* shape(int index) const;
	BNode* node(int index) const;
	BGroup* group(int index) const;

	BObject* object() const;
	BGroup* group() const;
	BNode* node() const;
	BShape* shape() const;
	BElement* element() const;

	bool empty() const;
	void clear();
	void dirty();

private:
	mutable bool				_dirtyBox;
	mutable BBox				_box;
	mutable bool				_dirtySpace;
	mutable BSpace				_space;
	BSceneHolder				_scene;
	BArray<BPickHitHolder>		_pickHits;
};

typedef BHolder<Target>		TargetHolder;

#endif
